using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Utilities;



namespace Services.Menu
{
    public class CustomKeyboard : OrientableScreen
    {
        SpriteBatch spritebatch;
        InputManager input_manager;
        protected MyButton title;
        protected MyButton confirmButton, cancelButton, textArea;
        protected Action<String> closeSelector;
        protected Action abortSelection;
        String titleString;
        protected ArrayList<MyButton> list;
        protected Texture2D white, confirm, cancel, circle;
        protected Texture2D key_background, key_back_p, key_enter_p, key_back_l, key_enter_l;
        public SpriteFont font, titleFont, smallFont;
        //String defaultString;
        public ArrayList<String> letters;
        List<ShortCut> ShortCuts = new List<ShortCut>();
        List<MyButton> hints = new List<MyButton>();
        string result;

        #region Constructors
        public CustomKeyboard(Game game, Action<String> closeSelector, Action abortSelection, String titleString, String defaultString,
            List<ShortCut> shortCuts)
            : base(game)
        {
            this.closeSelector = closeSelector;
            this.titleString = titleString;
            this.abortSelection = abortSelection;
            result = defaultString;
            ShortCuts = shortCuts;
        }

        #endregion

        public override void Initialize()
        {
            spritebatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));

            input_manager = new InputManager(Game);
            Game.Components.Add(input_manager);
            input_manager.OnTap += on_tap;

            //screen_transform = Game.ScreenTransformMatrix(graphics);

            font = Game.Content.Load<SpriteFont>("ItemSelector\\font");
            smallFont = Game.Content.Load<SpriteFont>("ItemSelector\\small");
            titleFont = Game.Content.Load<SpriteFont>("ItemSelector\\font");
            //small = Game.Content.Load<SpriteFont>("ItemSelector\\small");
            white = Game.Content.Load<Texture2D>("ItemSelector\\whitepixel");
            circle = Game.Content.Load<Texture2D>("ItemSelector\\circle");
            confirm = Game.Content.Load<Texture2D>("ItemSelector\\confirm");
            cancel = Game.Content.Load<Texture2D>("ItemSelector\\cancel");
            key_background = Game.Content.Load<Texture2D>("ItemSelector\\key_background");
            key_back_p = Game.Content.Load<Texture2D>("ItemSelector\\key_back_p");
            key_enter_p = Game.Content.Load<Texture2D>("ItemSelector\\key_enter_p");
            key_back_l = Game.Content.Load<Texture2D>("ItemSelector\\key_back_l");
            key_enter_l = Game.Content.Load<Texture2D>("ItemSelector\\key_enter_l");
            list = new ArrayList<MyButton>();
            letters = new ArrayList<string>() { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p",
                "a", "s", "d", "f", "g", "h", "j", "k", "l",
                "z", "x", "c", "v", "b", "n", "m" };
            base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {
            if (changed)
            {
                int finded = 0;
                for (int i = 0; i < hints.Count; i++)
                {
                    hints[i].text = "";
                    hints[i].enabled = false;
                }

                if (result != "")
                {
                    for (int i = 0; i < ShortCuts.Count; i++)
                    {
                        var a = ShortCuts[i];

                        if (a.shortcut.ToLower().StartsWith(result.ToLower()))
                        {
                            hints[finded].text = a.value;
                            hints[finded].enabled = true;
                            finded++;
                        }

                        if (finded == hints.Count)
                            break;
                    }
                }

                changed = false;
            }

            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            {

                Game.Components.Remove(input_manager);
                Game.Components.Remove(this);
                abortSelection();
                return;
            }
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            //spritebatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, screen_transform);
            spritebatch.Begin();

            for (int i = 0; i < list.Count; i++)
                list[i].Draw(spritebatch);
            title.Draw(spritebatch);
            cancelButton.Draw(spritebatch);
            confirmButton.Draw(spritebatch);
            textArea.Draw(spritebatch);

            k_back.Draw(spritebatch);
            k_enter.Draw(spritebatch);
            k_space.Draw(spritebatch);

            for (int i = 0; i < hints.Count; i++)
                hints[i].Draw(spritebatch);

            spritebatch.End();

            base.Draw(gameTime);
        }
        bool changed = false;
        void on_tap(Vector2 tap_pos)
        {
            //if (press_wait < PRESS_INTERVAL / 10) return;
            bool ok = false;
            if (cancelButton.tapped_on(tap_pos))
            {
                Game.Components.Remove(input_manager);
                Game.Components.Remove(this);
                abortSelection();
                return;
            }
            if (confirmButton.tapped_on(tap_pos))
            {
                Game.Components.Remove(input_manager);
                Game.Components.Remove(this);
                closeSelector(result);
                return;
            }
            if (k_space.tapped_on(tap_pos))
            {
                result += " ";
                changed = true;
            }
            else if (k_back.tapped_on(tap_pos))
            {
                if (result.Length <= 0)
                    return;
                result = result.Substring(0, result.Length - 1);
                changed = true;
            }
            else if (k_enter.tapped_on(tap_pos))
            {
                Game.Components.Remove(input_manager);
                Game.Components.Remove(this);
                closeSelector(result);
                return;
            }
            else
            {
                for (int i = 0; i < list.Count; i++)
                {
                    var a = list[i];
                    if (a.tapped_on(tap_pos))
                    {
                        result += a.text;
                        changed = true;
                        ok = true;
                        break;
                    }
                }
            }
            for (int i = 0; !ok && i < hints.Count; i++)
            {
                var a = hints[i];
                if (a.tapped_on(tap_pos) && a.text != "")
                {
                    result = a.text;
                    changed = false;
                    for (int j = 0; j < hints.Count; j++)
                    {
                        hints[j].text = "";
                        hints[j].enabled = false;
                    }
                    break;
                }
            }
            textArea.text = result;
        }

        public override void SetPortraitOrientation()
        {
            //surtitle = new MyButton(new Rectangle(20, 0, 200, 60), Strings.AppTitle, Color.White, font, TextPos.Left);
            title = new MyButton(new Rectangle(20, 0, 200, 80), titleString, Color.White, font, TextPos.Left);

            textArea = new MyButton(new Rectangle(20, 60, 440, 60), result, Color.Black, font,
                    TextPos.Center, white, Color.LightGray);
            cancelButton = new MyButton(new Rectangle(150, 730, 50, 50), cancel, Color.White, circle, Color.White);
            confirmButton = new MyButton(new Rectangle(280, 730, 50, 50), confirm, Color.White, circle, Color.White);
            BuildKeyboard(3, 380, 42, 78, 6, 6, true);

            if (hints.Count == 0)
            {
                hints.Add(new MyButton(new Rectangle(), "", Color.White, smallFont, TextPos.Center, key_background, Color.White));
                hints.Add(new MyButton(new Rectangle(), "", Color.White, smallFont, TextPos.Center, key_background, Color.White));
                hints.Add(new MyButton(new Rectangle(), "", Color.White, smallFont, TextPos.Center, key_background, Color.White));
                hints.Add(new MyButton(new Rectangle(), "", Color.White, smallFont, TextPos.Center, key_background, Color.White));
                for (int j = 0; j < hints.Count; j++)
                {

                    hints[j].enabled = false;
                }
            }
            
            for (int i = 0; i < hints.Count; i++)
            {
                hints[i].rectangle.X = textArea.rectangle.X;
                hints[i].rectangle.Y = textArea.rectangle.Y + textArea.rectangle.Height + 20 + i * (textArea.rectangle.Height * 3 / 4 + 10);
                hints[i].rectangle.Width = textArea.rectangle.Width;
                hints[i].rectangle.Height = textArea.rectangle.Height * 3 / 4;
            }
        }

        public override void SetLandScapeOrientation()
        {
            //surtitle = new MyButton(new Rectangle(100, 20, 200, 40), Strings.AppTitle, Color.White, font, TextPos.Left);
            title = new MyButton(new Rectangle(100, 20, 200, 60), titleString, Color.White, font, TextPos.Left);

            textArea = new MyButton(new Rectangle(100, 50, 650, 60), result, Color.Black, font,
                    TextPos.Center, white, Color.LightGray);
            cancelButton = new MyButton(new Rectangle(25, 150, 50, 50), cancel, Color.White, circle, Color.White);
            confirmButton = new MyButton(new Rectangle(25, 280, 50, 50), confirm, Color.White, circle, Color.White);
            BuildKeyboard(100, 240, 60, 50, 6, 6, false);

            if (hints.Count == 0)
            {
                hints.Add(new MyButton(new Rectangle(), "", Color.White, smallFont, TextPos.Center, key_background, Color.White));
                hints.Add(new MyButton(new Rectangle(), "", Color.White, smallFont, TextPos.Center, key_background, Color.White));
                hints.Add(new MyButton(new Rectangle(), "", Color.White, smallFont, TextPos.Center, key_background, Color.White));
                hints.Add(new MyButton(new Rectangle(), "", Color.White, smallFont, TextPos.Center, key_background, Color.White));
                for (int j = 0; j < hints.Count; j++)
                {

                    hints[j].enabled = false;
                }
            }
            
            for (int i = 0; i < hints.Count; i += 1)
            {
                if (i % 2 == 0)
                {
                    hints[i].rectangle.X = textArea.rectangle.X;
                    hints[i].rectangle.Y = textArea.rectangle.Y + textArea.rectangle.Height + 10 + i * (textArea.rectangle.Height / 3 + 10);
                    hints[i].rectangle.Width = textArea.rectangle.Width / 2 - 5;
                    hints[i].rectangle.Height = textArea.rectangle.Height * 3 / 4;
                }
                else
                {

                    hints[i].rectangle.X = textArea.rectangle.X + textArea.rectangle.Width / 2 + 5;
                    hints[i].rectangle.Y = hints[i - 1].rectangle.Y;
                    hints[i].rectangle.Width = hints[i - 1].rectangle.Width;
                    hints[i].rectangle.Height = hints[i - 1].rectangle.Height;
                }
            }
        }
        MyButton k_back, k_space, k_enter;
        public void BuildKeyboard(int x, int y, int width, int height, int offset_x, int offset_y, bool isPortrait)
        {
            list.Clear();
            int ori_x = x;
            int ori_y = y;
            for (int i = 0; i < 10; i++)
            {
                list.Add(new MyButton(new Rectangle(x + i * (width + offset_x), y, width, height), letters[i], Color.White, font, TextPos.Center, key_background, Color.White));
            }
            y += offset_y + height;
            x += width / 2;
            for (int i = 10; i < 19; i++)
            {
                list.Add(new MyButton(new Rectangle(x + (i - 10) * (width + offset_x), y, width, height), letters[i], Color.White, font, TextPos.Center, key_background, Color.White));
            }
            x += width + offset_x;
            y += offset_y + height;
            for (int i = 19; i < letters.Count; i++)
            {
                list.Add(new MyButton(new Rectangle(x + (i - 19) * (width + offset_x), y, width, height), letters[i], Color.White, font, TextPos.Center, key_background, Color.White));
            }
            k_back = new MyButton(new Rectangle(x + 7 * (width + offset_x), y, (offset_x + width * 3 / 2), height), (isPortrait ? key_back_p : key_back_l), Color.White);
            y += height + offset_y;

            list.Add(new MyButton(new Rectangle(x, y, width, height), "-", Color.White, font, TextPos.Center, key_background, Color.White));

            list.Add(new MyButton(new Rectangle(x + width + offset_x, y, width, height), "'", Color.White, font, TextPos.Center, key_background, Color.White));

            k_space = new MyButton(new Rectangle(x + 2 * (width + offset_x), y, 4 * (width + offset_y) - offset_y, height), "space", Color.White, font, TextPos.Center, key_background, Color.White);

            list.Add(new MyButton(new Rectangle(x + 6 * (width + offset_x), y, width, height), ".", Color.White, font, TextPos.Center, key_background, Color.White));

            k_enter = new MyButton(new Rectangle(x + 7 * (width + offset_x), y, (offset_x + width * 3 / 2), height), (isPortrait ? key_enter_p : key_enter_l), Color.White);
        }
    }
}
